/**
 * FlightManager.java
 * Dec 20, 2009
 */
package com.dlplay.flightinfo.core;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import com.dlplay.flightinfo.data.AirFlightCode;
import com.dlplay.flightinfo.data.CityCode;
import com.dlplay.flightinfo.data.EMailRegister;
import com.dlplay.flightinfo.data.FlightInfo;
import com.dlplay.flightinfo.data.RealTimeFlightInfo;
import com.dlplay.flightinfo.source.RealTimeFlightDS;


/**
 * @author zhao yu
 *
 */
public class SimpleFlightManager implements FlightManager {
	private static final Logger log = Logger.getLogger(SimpleFlightManager.class.getName());		
	
	/**
	 * @param user
	 * @param flightNum
	 * @param email
	 * @return if failed, return null
	 * Description: register a flight number, 
	 * when the flight info is changed, notify the user by email
	 */
	@Override
	public boolean registerEmail(String user, AirFlightCode flightNum, String email) {
		log.info("register flight : "+flightNum+" user: "+user+" email: "+email);
		RealTimeFlightInfo rtInfo = getRealTimeFlightInfo(flightNum);
		if(rtInfo==null)
		{
			log.info("register failed: no flight");
			return false;
		}
		
		EMailRegister reg = FlightSystem.getFlightInfoDbManager().getFlightEmailRegister(flightNum, email);
		if(reg!=null)
		{
			log.info("register already exist");
			return false;
		}
		log.info("add a new register");
		reg = new EMailRegister(user, flightNum.getCode(), flightNum.getNumber(), email);				
		FlightSystem.getFlightInfoDbManager().addFlightRegister(reg);
		reg.welcome(rtInfo);
		return true;
	}

	@Override
	public FlightInfo getFlightInfo(AirFlightCode flightNumber, Date date) {
		if(date.before(new Date()))
		{
			//if the date is before today, return null
			return null;
		}
		//check it in database
		FlightInfo flightInfo = FlightSystem.getFlightInfoDbManager().getFlightInfo(flightNumber, date);
		if(flightInfo==null)
		{
			log.info("no found flight info: "+flightNumber);
			return null;
		}
		else
		{
			log.info("found flight info: "+flightNumber);
			return flightInfo;
		}		
	}

	@Override
	public FlightInfo getFlightInfo(AirFlightCode flightNumber) {
		return getFlightInfo(flightNumber, new Date());
	}

	@Override
	public RealTimeFlightInfo getRealTimeFlightInfo(AirFlightCode flightNumber) {
		log.info("get flight realtime info: "+flightNumber);
		RealTimeFlightInfo oldInfo = FlightSystem.getFlightInfoDbManager().getRealTimeFlightInfo(flightNumber);
		if(oldInfo==null)
		{
			log.info("no hit in DB");
			//try to update the info by datasource
			List<RealTimeFlightDS> rtFlightDSList = FlightSystem.getDataSourceManager().getRealTimeFlightDS();
			log.info("found "+rtFlightDSList.size()+" RTFlightDataSource");
			for(int i=0; i<rtFlightDSList.size(); i++)
			{
				
				RealTimeFlightInfo newInfo = rtFlightDSList.get(i).getFlightByNum(flightNumber);
				if(newInfo!=null)
				{
					log.info("success to get rt flight info: "+newInfo);
					//TODO: id_2, dont break here, merge the data source
					FlightSystem.getFlightInfoDbManager().addRealTimeFlightInfo(newInfo);
					notifyRealTimeFlightChanged(flightNumber, null, newInfo);
					return newInfo;
				}
				else
				{
					log.info("failed to get rt flight info");
				}
			}
			
		}else if(oldInfo.getLatestUpdate()==null ||System.currentTimeMillis()-oldInfo.getLatestUpdate().getTime()>Constants.AGING_TIME)
		{
			log.info("data in DB is old: "+oldInfo.getLatestUpdate());
			//try to update the info by datasource
			List<RealTimeFlightDS> rtFlightDSList = FlightSystem.getDataSourceManager().getRealTimeFlightDS();
			log.info("found "+rtFlightDSList.size()+" RTFlightDataSource");
			for(int i=0; i<rtFlightDSList.size(); i++)
			{
				
				RealTimeFlightInfo newInfo = rtFlightDSList.get(i).getFlightByNum(flightNumber);
				if(newInfo!=null)
				{
					log.info("success to get rt flight info: "+newInfo);
					//TODO: id_2, dont break here, merge the data source
					if(!newInfo.compare(oldInfo))
					{
						log.info("oldInfo: "+oldInfo.getLatestUpdate());
						FlightSystem.getFlightInfoDbManager().updateRealTimeFlightInfo(newInfo);
						notifyRealTimeFlightChanged(flightNumber, oldInfo, newInfo);
					}
					return newInfo;
				}
				else
				{
					log.info("failed to get rt flight info");
				}
			}
		}else
		{
			log.info("hit in DB: "+oldInfo);
			return oldInfo;
		}
		return null;
	}

	private void notifyRealTimeFlightChanged(AirFlightCode flightNumber,
			RealTimeFlightInfo oldInfo, RealTimeFlightInfo info) {
		// TODO id_4, notify the reigster user
		
	}

	@Override
	public List<FlightInfo> searchFlightInfo(CityCode from, CityCode to,
			Date date) {
		log.info("search flight, "+"from: "+from+" to: "+to+" date: "+date);
		if(date.before(new Date()))
		{
			//if the date is before today, return null
			return new ArrayList<FlightInfo>();
		}
		//check it in database
		List<FlightInfo> flights = FlightSystem.getFlightInfoDbManager().getFlightInfo(from, to, date);
		if(flights.isEmpty())
		{
			log.info("no found flight");
			return new ArrayList<FlightInfo>();
		}
		else
		{
			log.info("found "+flights.size()+" flights");
			return flights;
		}	
	}

	@Override
	public List<FlightInfo> searchFlightInfo(CityCode from, CityCode to) {		
		return searchFlightInfo(from, to, new Date());
	}		
}
